package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.json.JSONUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.constant.CacheConstants;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliIoTConfigProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.vo.ProductVo;
import com.zzyl.vo.retreat.DeviceVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class DeviceServiceImpl implements DeviceService {

    @Autowired
    private AliIoTConfigProperties aliIoTConfigProperties;
    @Autowired
    private Client client;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private DeviceMapper deviceMapper;
    @Override
    public void qureyDeviceList() {
        QueryProductListRequest request = new QueryProductListRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setCurrentPage(1);
        request.setPageSize(100);
        QueryProductListResponse queryProductListResponse = null;
        try {
            queryProductListResponse = client.queryProductList(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (queryProductListResponse.getBody().success){
            List<QueryProductListResponseBody.QueryProductListResponseBodyDataListProductInfo> productInfo = queryProductListResponse.getBody().getData().getList().getProductInfo();
            redisTemplate.opsForValue().set(CacheConstants.DEVICE_PRODUCT, JSONUtil.toJsonStr(productInfo));
        }

    }

    @Override
    public List<ProductVo> getAllProduct() {
        String s = redisTemplate.opsForValue().get(CacheConstants.DEVICE_PRODUCT);
        List<ProductVo> list = JSONUtil.toList(s, ProductVo.class);
        return list;
    }

    @Override
    public void registerDevice(DeviceDto deviceDto) {
        int count = deviceMapper.getdeviceByName(deviceDto.getDeviceName());
        //1.判断设备名称是否重复 去数据库差询 现有的设备
        if (count>0){
            throw new BaseException(BasicEnum.DEVICE_NAME_EXIST);
        }
        //2.在IOT新增设备
        //2.1 获取产品信息  把信息set到物联网上注册
        RegisterDeviceRequest registerDeviceRequest = new RegisterDeviceRequest();
        registerDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        registerDeviceRequest.setDeviceName(deviceDto.getDeviceName());
        registerDeviceRequest.setProductKey(deviceDto.getProductKey());
        registerDeviceRequest.setNickname(deviceDto.getNickname());
        RegisterDeviceResponse response = null;
        try {
            response = client.registerDevice(registerDeviceRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }
        if(!response.getBody().success){
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }
        //3.在数据库中新增
        //3.1 获取设备信息
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        //通过返回值设置id
        device.setIotId(response.getBody().getData().getIotId());
        //设置门禁
        device.setHaveEntranceGuard(0);
        QueryProductRequest queryProductRequest = new QueryProductRequest();
        queryProductRequest.setProductKey(deviceDto.getProductKey());
        queryProductRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryProductResponse queryProductResponse = null;
        try {
            queryProductResponse = client.queryProduct(queryProductRequest);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        //设置设备名称
        device.setProductName(queryProductResponse.getBody().getData().productName);
        //3.2如果位置类型为0 设置物理位置类型为-1
        if (device.getLocationType().equals(0)){
            device.setPhysicalLocationType(-1);
        }
        //开始向数据库插入数据
        try {
            deviceMapper.inseret(device);
        } catch (Exception e) {
            //插入数据库失败 删除物联网
            DeleteDeviceRequest request = new DeleteDeviceRequest();
            request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
            request.setProductKey(deviceDto.getProductKey());
            request.setDeviceName(deviceDto.getDeviceName());
            DeleteDeviceResponse deleteDeviceResponse=null;
            try {
                deleteDeviceResponse = client.deleteDevice(request);
            } catch (Exception ex) {
                throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
            }
            if (!deleteDeviceResponse.getBody().success){
                throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
            }
        }


    }

    @Override
    public PageResponse<DeviceVo> pageQueryDevice(DevicePageQueryDto devicePageQuery) {
        PageHelper.startPage(devicePageQuery.getPageNum(),devicePageQuery.getPageSize());
        //传入设备名称 位置类型 产品名称
        Page<DeviceVo> deviceVos = deviceMapper.pageQueryDevice(devicePageQuery);
        return PageResponse.of(deviceVos,DeviceVo.class);
    }

    @Override
    public DeviceVo queryDeviceDetail(DeviceDto deviceDto) {
        //1.查询数据库中的产品设备信息
        DeviceVo deviceVo = deviceMapper.queryDeviceDetail(deviceDto.getIotId());
        //2.查询物联网中的设备信息
        QueryDeviceDetailRequest queryProductRequest = new QueryDeviceDetailRequest();
        queryProductRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        queryProductRequest.setIotId(deviceDto.getIotId());
        queryProductRequest.setProductKey(deviceDto.getProductKey());
        QueryDeviceDetailResponse response = null;
        try {
            response =  client.queryDeviceDetail(queryProductRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }
        if (!response.getBody().success){
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }
        QueryDeviceDetailResponseBody.QueryDeviceDetailResponseBodyData data = response.getBody().getData();
        //3.合并数据 并返回
        BeanUtil.copyProperties(data,deviceVo, CopyOptions.create().ignoreNullValue());
        return deviceVo;
    }

    @Override
    public QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyData queryDevicePropertyStatus(DeviceVo deviceDto) {
        QueryDevicePropertyStatusRequest request = new QueryDevicePropertyStatusRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setProductKey(deviceDto.getProductKey());
        request.setIotId(deviceDto.getIotId());
        request.setDeviceName(deviceDto.getDeviceName());
        QueryDevicePropertyStatusResponse queryDevicePropertyStatusResponse = null;
        try {
            queryDevicePropertyStatusResponse = client.queryDevicePropertyStatus(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if (!queryDevicePropertyStatusResponse.getBody().success){
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }
        QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyData data = queryDevicePropertyStatusResponse.getBody().getData();
        return data;
    }

    @Override
    public QueryThingModelPublishedResponseBody.QueryThingModelPublishedResponseBodyData queryThingModelPublished(DeviceVo deviceDto) {
        QueryThingModelPublishedRequest request = new QueryThingModelPublishedRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setProductKey(deviceDto.getProductKey());
        QueryThingModelPublishedResponse queryThingModelPublishedResponse = null;
        try {
            queryThingModelPublishedResponse = client.queryThingModelPublished(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }
        if (!queryThingModelPublishedResponse.getBody().success){
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }
        QueryThingModelPublishedResponseBody.QueryThingModelPublishedResponseBodyData data = queryThingModelPublishedResponse.getBody().getData();
        return data;
    }

    @Override
    public void updateDevice(DeviceDto deviceDto) {
        //1.修改数据库中的数据
        if(deviceDto.getLocationType()==0){
            deviceDto.setPhysicalLocationType(-1);
        }
        deviceMapper.updateDevice(deviceDto);
        //2.修改物联网中的数据
        BatchUpdateDeviceNicknameRequest request = new BatchUpdateDeviceNicknameRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo deviceNicknameInfo = new BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo();
        BeanUtil.copyProperties(deviceDto,deviceNicknameInfo);
        List<BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo> deviceNicknameInfos = new ArrayList<>();
        deviceNicknameInfos.add(deviceNicknameInfo);
        request.setDeviceNicknameInfo(deviceNicknameInfos);
        try {
            client.batchUpdateDeviceNickname(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }
    }

    @Override
    public void deleteDevice(DeviceDto deviceDto) {
        //1.先删除数据库中的数据
        deviceMapper.deleteDevice(deviceDto.getIotId());
        //2.删除物联网中的数据
        DeleteDeviceRequest request = new DeleteDeviceRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setProductKey(deviceDto.getProductKey());
        request.setIotId(deviceDto.getIotId());
        try {
            client.deleteDevice(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }
    }

}
